﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;

namespace Workflows.Components.ETL
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class DownloadTablesInstruction:InstructionBase
    {
        #region props
        private string _ConnStr;
        /// <summary></summary>
        public string ConnStr
        {
            get
            {
                return this._ConnStr;
            }
            set
            {
                this._ConnStr = value;
            }
        }

        private Dictionary<string,List<string>> _TablesBySchema;
        /// <summary></summary>
        public Dictionary<string,List<string>> TablesBySchema
        {
            get
            {
                return this._TablesBySchema;
            }
            set
            {
                this._TablesBySchema = value;
            }
        }

        private Dictionary<string, string> _TablesBySql;
        /// <summary></summary>
        public Dictionary<string, string> TablesBySql
        {
            get
            {
                return this._TablesBySql;
            }
            set
            {
                this._TablesBySql = value;
            }
        }

        private string _TargetFolderPath;
        /// <summary></summary>
        public string TargetFolderPath
        {
            get
            {
                return this._TargetFolderPath;
            }
            set
            {
                this._TargetFolderPath = value;
            }
        }

        private FileFormat _TgtFileFormat;
        /// <summary></summary>
        public FileFormat TgtFileFormat
        {
            get
            {
                return this._TgtFileFormat;
            }
            set
            {
                this._TgtFileFormat = value;
            }
        }
        #endregion

        #region ctor
        /// <summary>
        /// 
        /// </summary>
        public DownloadTablesInstruction():base(Guid.Empty,Guid.Empty)
        {
            this._ConnStr = string.Empty;
            this._TablesBySchema=new Dictionary<string, List<string>>();
            this._TablesBySql = new Dictionary<string, string>();
            this._TargetFolderPath = string.Empty;
            this._TgtFileFormat = FileFormat.ExcelFile;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="componentID"></param>
        /// <param name="jobTicketID"></param>
        /// <param name="connStr"></param>
        /// <param name="schemaTbls"></param>
        /// <param name="tgtFolder"></param>
        /// <param name="tgtFormat"></param>
        public DownloadTablesInstruction(Guid componentID, Guid jobTicketID,
            string connStr, Dictionary<string,List<string>> schemaTbls,
            Dictionary<string,string> sqlTbls,
            string tgtFolder, FileFormat tgtFormat) 
            : base(componentID, jobTicketID)
        {
            this._ConnStr = connStr;
            this._TablesBySchema = schemaTbls;
            this._TablesBySql = sqlTbls;
            this._TargetFolderPath = tgtFolder;
            this._TgtFileFormat = tgtFormat;
        }
        #endregion

        #region Overrides of InstructionBase

        /// <summary>
        /// serialize settings to xml
        /// the function below is mainly for storing into database as serialized form instead of string
        /// </summary>
        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = XmlDataUtil.AddElement(ref xDoc, parentNode, "Instruction");
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Type", this.GetType().FullName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ComponentID", this.OwnerComponentID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "WorkerID", this.OwnerWorkerInstanceID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SubmitTime", this.SubmitTime.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "StartTime", this.StartTime.ToString());

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ConnStr", this.ConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtFolder", this.TargetFolderPath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtFormat", this.TgtFileFormat.ToString());
            XmlNode schemaNodes = XmlDataUtil.AddElement(ref xDoc, xNode, "Schemas");
            if(this.TablesBySchema !=null && this.TablesBySchema.Count>0)
            {
                foreach(string schemaName in this.TablesBySchema.Keys)
                {
                    XmlNode schemaNode = XmlDataUtil.AddElement(ref xDoc, schemaNodes, "Schema");
                    XmlDataUtil.UpdateAttribute(ref xDoc, schemaNode, "SchemaName",schemaName);
                    foreach(string tbl in this.TablesBySchema[schemaName])
                    {
                        XmlNode tblNode = XmlDataUtil.AddElement(ref xDoc, schemaNode, "Table");
                        XmlDataUtil.UpdateAttribute(ref xDoc, tblNode, "TableName",tbl);
                    }
                }
            }
            XmlNode sqlNodes = XmlDataUtil.AddElement(ref xDoc, xNode, "Sqls");
            if (this.TablesBySql != null && this.TablesBySql.Count > 0)
            {
                foreach (string tblName in this.TablesBySql.Keys)
                {
                    XmlNode sqlNode = XmlDataUtil.AddElement(ref xDoc, sqlNodes, "Sql");
                    XmlDataUtil.UpdateAttribute(ref xDoc, sqlNode, "TableName", tblName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, sqlNode, "Sql", this.TablesBySql[tblName]);
                }
            }

            return xNode;
        }

        /// <summary>
        /// instantiated from xml
        /// "&lt;Instructions&gt;&lt;Instruction&gt;&lt;/Instruction&gt;&lt;/Instruction&gt;", must
        /// instantiate from first child of root node
        /// </summary>
        public override InstructionBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                DownloadTablesInstruction instruction = new DownloadTablesInstruction();
                instruction.OwnerComponentID = new Guid(xNode.Attributes.GetNamedItem("ComponentID").Value);
                instruction.OwnerWorkerInstanceID = new Guid(xNode.Attributes.GetNamedItem("WorkerID").Value);
                instruction.SubmitTime = DateTime.Parse(xNode.Attributes.GetNamedItem("SubmitTime").Value);
                instruction.StartTime = DateTime.Parse(xNode.Attributes.GetNamedItem("StartTime").Value);

                instruction.ConnStr = XmlDataUtil.GetAttributeValue(xNode, "ConnStr", "");
                instruction.TargetFolderPath = XmlDataUtil.GetAttributeValue(xNode, "TgtFolder", "");
                instruction.TgtFileFormat =
                    (FileFormat) Enum.Parse(
                                     typeof (FileFormat),
                                     XmlDataUtil.GetAttributeValue(
                                         xNode, "TgtFormat", FileFormat.ExcelFile.ToString()));
                instruction.TablesBySchema=new Dictionary<string, List<string>>();
                XmlNodeList schemaNodes = xNode.SelectNodes("Schemas/Schema");
                foreach(XmlNode schemaNode in schemaNodes)
                {
                    string schemaName = XmlDataUtil.GetAttributeValue(schemaNode, "SchemaName", "");
                    List<string> tblNames=new List<string>();
                    foreach(XmlNode tblNode in schemaNode.ChildNodes)
                    {
                        string tblName = XmlDataUtil.GetAttributeValue(tblNode, "TableName", "");
                        tblNames.Add(tblName);
                    }
                    instruction.TablesBySchema.Add(schemaName, tblNames);
                }
                instruction.TablesBySql = new Dictionary<string, string>();
                XmlNodeList sqlTblNodes = xNode.SelectNodes("Sqls/Sql");
                if (sqlTblNodes != null && sqlTblNodes.Count > 0)
                {
                    foreach (XmlNode sqlNode in sqlTblNodes)
                    {
                        string tblName = XmlDataUtil.GetAttributeValue(sqlNode, "TableName", "");
                        string sql = XmlDataUtil.GetAttributeValue(sqlNode, "Sql", "");
                        instruction.TablesBySql.Add(tblName, sql);
                    }
                }

                return instruction;
            }
            else
            {
                throw new Exception("Unable to instantiate instruction: invalid type specified in xml node");
            }
        }

        #endregion
    }
}
